//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.IO;

namespace OpenLS.Spreadsheet.Formats.Biff.Records
{
    internal sealed class SstRecord : BiffRecord, IWorkbookPass2Record
    {
        List<XLUnicodeRichExtendedString> rgb  = new List<XLUnicodeRichExtendedString>();
        private int _count;
        private int _totalStringCount;
        private byte[] _buffer;

        public SstRecord(int count, IEnumerable<XLUnicodeRichExtendedString> strings)
        {
            _count = count;
            _totalStringCount = count;
            Contract.Requires(strings != null);
            Contract.Assert(Enumerable.Sum(strings, s => s.Length) < 9000);
            foreach (var v in strings)
            {
                    rgb.Add(v);
            }
        }
        public SstRecord()
        {
        }

        

        #region IWorkbookPass2Record Members

        public void Apply(BiffReaderWorkbookContext context)
        {
            context.Workbook.SharedStrings = new SharedStrings();
            int stringId = 0;
            foreach (var s in this.rgb)
            {
                int stringIndex = context.Workbook.SharedStrings.GetIndex((string)s); //\\
                context.StringIdToStringIndexTable.Add(stringId, stringIndex);
                stringId++;
            }
#if DEBUG
            foreach (var s in rgb)
            {
                //\\Debug.WriteLine(s);
            }
#endif
        }

        #endregion

        internal override BiffRecordType RecordType
        {
            get { return BiffRecordType.SST; }
        }

        internal override void WriteContent(BiffWriterWorkbookContext context)
        {
            var totalStringCount = _count;
            context.Write(totalStringCount);
            var count = _count;
            context.Write(count);
            foreach (var xlUnicodeRichExtendedString in rgb)
            {
                xlUnicodeRichExtendedString.Write(context.Writer);

            }
        }

        protected override void ReadContent(BiffReaderContext context, int length)
        {

            _totalStringCount = context.ReadInt32();
            _count = context.ReadInt32();
            Contract.Assert((_count == 0) == (length == 8));
           _buffer = context.ReadBytes(length - 4 - 4);
        }

        public override void ReadWithContinue()
        {
            var readers = new List<BinaryReader> {new BinaryReader(new MemoryStream(_buffer))};
            var buffers=  new List<byte[]> {_buffer};
            foreach (var continueRecord in this.GetFollowingContinueRecords())
            {
                readers.Add(new BinaryReader(new MemoryStream(continueRecord.Buffer)));
                buffers.Add(continueRecord.Buffer);
                
            }
            /*
            var continueRecord = Next as ContinueRecord;
            while (continueRecord != null)
            {
                continueRecord = continueRecord.Next as ContinueRecord;
            }*/
            //List<byte> allBytes = Enumerable.ToList(Enumerable.SelectMany( buffers, b => b));
            MultiBinaryReader multiBinaryReader = new MultiBinaryReader(buffers);
            for (int i = 0; i < this._count; i++ )
            {
                var toAdd = XLUnicodeRichExtendedString.Read(multiBinaryReader);
                rgb.Add(toAdd);
            }
        }
        [Obsolete]
        public  void ReadWithContinueObsolete()
        {
            var readers = new List<BinaryReader> { new BinaryReader(new MemoryStream(_buffer)) };
            var continueRecord = Next as ContinueRecord;
            var buffers = new List<byte[]> { _buffer };
            while (continueRecord != null)
            {
                readers.Add(new BinaryReader(new MemoryStream(continueRecord.Buffer)));
                buffers.Add(continueRecord.Buffer);
                continueRecord = continueRecord.Next as ContinueRecord;
            }
            List<byte> allBytes = Enumerable.ToList(Enumerable.SelectMany(buffers, b => b));
            MultiBinaryReader multiBinaryReader = new MultiBinaryReader(buffers);
            for (int i = 0; i < this._count; i++)
            {
                var toAdd = XLUnicodeRichExtendedString.Read(multiBinaryReader);
                rgb.Add(toAdd);
            }
        }
    }
}